跳到主要内容

Vue3 中的 keep-alive

转载自 vue3项目keepAlive使用方法详解

keep-alive 是什么?

<keep-alive> 是Vue的内置组件,能在组件切换过程中 将状态保留在内存 中(类似 Unity 那种场景池),防止重复渲染DOM。

<keep-alive> 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们。和 <transition> 相似,<keep-alive> 是一个抽象组件:它自身不会渲染一个 DOM 元素,也不会出现在父组件链中。

配置了 keepalive 的路由或者组件,只会在页面初始化的时候执行 created => mounted 生命周期,第二次及以后再进入该页面将不会执行该生命周期,而是会去读取缓存信息。

router 配置缓存

第一步:配置 App.vue

vue2.xvue3.0 的 App.vue 配置有差异,在 App.vue 配置信息如下:

vue2.x 中,router-view 可整个放入 keepalive 中,如下:

<template>
<!-- vue2.x配置 -->
<keep-alive>
<router-view v-if="$route.meta.keepAlive" />
</keep-alive>
<router-view v-if="!$route.meta.keepAlive"/>
</template>

vue3.0 的 App.vue 配置方法如下:

<template>
<!-- vue3.0配置 -->
<router-view v-slot="{ Component }">
<keep-alive>
<component :is="Component" v-if="$route.meta.keepAlive"/>
</keep-alive>
<component :is="Component" v-if="!$route.meta.keepAlive"/>
</router-view>
</template>

这里 component 是 vue 中的特殊组件,:is 是用来绑定指定组件,这里是与路由对应的页面绑定。

第二步:添加 meta 属性

在对应的路由上添加 meta 属性来设置页面是否要使用缓存,如下:

{
path: "/keepAliveTest",
name: "keepAliveTest",
meta: {
keepAlive: true //设置页面是否需要使用缓存
},
component: () => import("@/views/keepAliveTest/index.vue")
},

到此即可实现页面的简单缓存,但是有些场景需要做复杂处理,比如说页面部分信息不需要读缓存,每次进入都需要进行处理,这个时候我们就可以使用activated 生命周期来解决页面部分刷新问题。

实现页面部分刷新

先了解 vue 的生命周期,被 keepAlive 包裹的组件和页面,页面进入时执行的生命周期为:created => mounted => activated;

其中 created => mounted 是页面第一次进入才会执行,activated 生命周期在页面每次进入都会执行,特属于 keepAlive 的一个生命周期,所以我们把页面每次进来要进行的操作放入该生命周期即可。

如下代码:

activated() {
// 页面每次进入将手机动态验证码置为空
this.$refs.mobPwdCode.inputValue = '';
},

实现的功能是用户每次进入将动态验证码设为空,实现此功能也可以用其他方式,比如说将该组件放缓存外(参见2、component 配置缓存)。

动态设置路由 keepAlive 属性

有些时候我们用完了 keepalive 缓存之后,想让页面不再保持缓存,或者设置下一个页面 keepalive,也这个时候我们可以改变 meta 的 keepAlive 值来去除页面缓存,使用 beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave,使用方式如下:

// to为即将跳转的路由,from为上一个页面路由
beforeRouteLeave(to, from,+ next) {
// 设置下一个路由的 meta
to.meta.keepAlive = false;
next();
}

组件配置缓存

使用场景

通常我们会对 vue 的一个页面进行缓存,然而有些时候我们仅需要缓存页面的某一个组件,或是在使用动态组件 compent 进行组件切换时需要对组件进行缓存。

缓存页面指定组件

当用于 App.vue 时,所有的路由对应的页面为项目所对应的组件,使用方法如下:

在 keep-alive 组件上使用 include 或 exclude 属性,如下:使用 include 代表将缓存 name 为 testKA 的组件

<!-- APP.vue文件,将页面作为组件缓存 -->
<router-view v-slot="{ Component }">
<keep-alive include="testKA">
<component :is="Component"/>
</keep-alive>
</router-view>

在 router 对应的页面中,需要设置 name 属性,如下:

export default {
name:'testKA',// keep-alive中include属性匹配组件name
data() {return {}},
activated() {
// keepalive缓存的页面每次进入都会进行的生命周期
},
}

此外,include 用法还有如下:

<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
<component :is="view"></component>
</keep-alive>

<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
<component :is="view"></component>
</keep-alive>

<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
<component :is="view"></component>
</keep-alive>

exclude 用法与 include 用法相同,代表不被缓存的组件。此外,keep-alive 还有一个 max 属性,代表缓存组件最大数量,一旦这个数字达到了,在新实例被创建之前,已缓存组件中最久没有被访问的实例会被销毁掉。

<keep-alive :max="10">
<component :is="view"></component>
</keep-alive>

当用于某个页面进行组件切换时,用法与缓存路由相同,不过只是将页面降级为一个组件,父组件由 App.vue 降级为对应路由页面。

子组件不能跨级使用

keepalive 缓存组件时,不能跨级使用,比如在 App.vue 中使用 include 属性进行 name="a" 匹配时,只能匹配缓存 name 为 a 的子组件(路由页面),而不能缓存 nam e为 "a" 的孙子组件(子页面引的组件)。若想缓存孙子组件,可以将整个子组件缓存,或者在子组件里再使用 keepalive。